package com.stellar.circle.rpc;


import cn.hutool.json.JSONUtil;
import com.stellar.auth.api.UserFeignClient;
import com.stellar.auth.api.dto.UserInfoDTO;
import com.stellar.circle.utils.RetryUtils;
import com.stellar.redis.core.constants.RedisKeyConstants;
import com.stellar.redis.core.util.RedisUtil;
import com.stellar.web.core.bean.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: Jqchan_
 */
@Component
@Slf4j
public class UserRPC {

    @Resource
    private UserFeignClient userFeignClient;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 根据用户id查询用户信息
     *
     * @param uid 用户ID（必须为正整数）
     * @return 用户信息DTO，不存在时返回空对象（非null）
     * @throws IllegalArgumentException 当uid为null或非法值时抛出
     */
    public UserInfoDTO queryUserInfoByUid(Long uid) {
        // 参数校验
        if (uid == null || uid <= 0) {
            log.warn("非法用户ID查询: {}", uid);
            throw new IllegalArgumentException("用户ID不能为空且必须为正整数");
        }

        final String cacheKey = redisUtil.buildKey(RedisKeyConstants.USER_INFO.getCachePrefix(), uid.toString());

        // 缓存查询
        try {
            String cacheInfo = redisUtil.get(cacheKey);
            if (StringUtils.isNotBlank(cacheInfo)) {
                try {
                    return JSONUtil.toBean(cacheInfo, UserInfoDTO.class);
                } catch (Exception e) {
                    log.error("用户信息缓存反序列化失败 [uid:{}, cacheData:{}]，执行缓存删除", uid, cacheInfo, e);
                    redisUtil.del(cacheKey);
                }
            }
        } catch (Exception e) {
            log.error("缓存查询异常 [uid:{}]，继续执行下游查询", uid, e);
        }

        // 缓存未命中，查询下游服务
        UserInfoDTO userInfo;
        try {
            Result<UserInfoDTO> result = userFeignClient.getById(uid);

            if (result == null || !result.getSuccess()) {
                log.warn("用户信息查询失败 [uid:{}], 返回空对象", uid);
                // 构建空对象并缓存防穿透
                userInfo = createEmptyUserInfo();
            } else {
                userInfo = result.getData();
                // 处理用户不存在的情况
                if (userInfo == null) {
                    log.info("用户不存在 [uid:{}]", uid);
                    userInfo = createEmptyUserInfo();
                }
            }
        } catch (Exception e) {
            log.error("用户信息查询服务异常 [uid:{}]", uid, e);
            userInfo = createEmptyUserInfo();
        }

        return userInfo;
    }


    private static final int MAX_BATCH_SIZE = 1000; // 类常量


    /**
     * 批量查询用户信息
     *
     * @param ids 用户ID列表（允许为空）
     * @return 用户信息列表（不会返回null，可能为空列表）
     */
    public List<UserInfoDTO> batchQueryByIds(List<Long> ids) {
        // 空参数快速返回
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }

        // 去重并限制最大数量（防止超大请求）
        Set<Long> uniqueIds = new LinkedHashSet<>(ids);
        if (uniqueIds.size() > MAX_BATCH_SIZE) {
            uniqueIds = uniqueIds.stream()
                    .limit(MAX_BATCH_SIZE)
                    .collect(Collectors.toCollection(LinkedHashSet::new));
            log.warn("BatchQueryByIds exceeded max size ({}), truncated to {}", ids.size(), MAX_BATCH_SIZE);
        }

        // 分批调用（避免单次请求过大）
        List<UserInfoDTO> result = new ArrayList<>();
        List<Long> idList = new ArrayList<>(uniqueIds);

        int batchSize = 200; // 每批200个ID
        for (int i = 0; i < idList.size(); i += batchSize) {
            int end = Math.min(i + batchSize, idList.size());
            List<Long> batchIds = idList.subList(i, end);

            try {
                // 添加重试机制
                List<UserInfoDTO> batchResult = RetryUtils.retry(() ->
                                userFeignClient.batchQueryByIds(batchIds).getData(),
                        3, 100, "batchQueryUserInfo"
                );

                if (batchResult != null) {
                    result.addAll(batchResult);
                }
            } catch (Exception e) {
                log.error("Batch query user info failed for ids: {}", batchIds, e);
                // 部分失败降级处理
                // 可以添加熔断或降级策略
            }
        }

        return result;
    }

    /**
     * 创建空用户信息对象（防缓存穿透专用）
     */
    private UserInfoDTO createEmptyUserInfo() {
        return UserInfoDTO.builder()
                .avatar("")
                .nickName("")
                .build();
    }

    /**
     * 根据学校ID查询用户数量
     *
     * @param id
     * @return
     */
    public Long countBySchoolId(Long id) {
        Result<Long> longResult = userFeignClient.countBySchoolId(id);
        if (!longResult.getSuccess()) {
             return 0L;
        }
        return longResult.getData();
    }
}
